Return to start page
Systems/Character/Struct Video.j
1 library AStructSystemsCharacterVideo requires optional ALibraryCoreDebugMisc, AStructCoreGeneralVector, ALibraryCoreGeneralPlayer, ALibraryCoreGeneralUnit, AStructCoreInterfacePlayerSelection, ALibraryCoreInterfaceMisc, ALibraryCoreStringConversion, AStructSystemsCharacterCharacter
2
3 private struct AActorData
4 //start members
5 private unit m_unit
6 //members
7 private unit m_actor
8
9 //start members
10
11 public method unit takes nothing returns unit
12 return this.m_unit
13 endmethod
14
15 //members
16
17 public method actor takes nothing returns unit
18 return this.m_actor
19 endmethod
20
21 //methods
22
23 public method restore takes nothing returns nothing
24 call RemoveUnit(this.m_actor)
25 set this.m_actor = null
26 call ShowUnit(this.m_unit, true)
27 endmethod
28
29 public method restoreOnActorsLocation takes nothing returns nothing
30 call BJDebugMsg("restore on actors location")
31 call SetUnitX(this.m_unit, GetUnitX(this.m_actor))
32 call SetUnitY(this.m_unit, GetUnitY(this.m_actor))
33 call SetUnitFacing(this.m_unit, GetUnitFacing(this.m_actor))
34 call this.restore()
35 endmethod
36
37 public static method create takes unit oldUnit returns thistype
38 local thistype this = thistype.allocate()
39 //local player newOwner = Player(PLAYER_NEUTRAL_PASSIVE) // set passive owner so unit won't attack or be attacked
40 //start members
41 call ShowUnit(oldUnit, false)
42 set this.m_unit = oldUnit
43 //members
44 set this.m_actor = CopyUnit(oldUnit, GetUnitX(oldUnit), GetUnitY(oldUnit), GetUnitFacing(oldUnit), bj_UNIT_STATE_METHOD_MAXIMUM)
45 //call SetUnitOwner(this.m_actor, newOwner, false)
46 call ShowUnit(this.m_actor, true)
47 if (IsUnitHidden(this.m_actor)) then
48 call ShowUnit(this.m_actor, true)
49 endif
50 if (IsUnitPaused(this.m_actor)) then
51 call PauseUnit(this.m_actor, false)
52 endif
53 call SelectUnit(this.m_actor, false)
54 call SetUnitInvulnerable(this.m_actor, true)
55 call IssueImmediateOrder(this.m_actor, "stop") //cancel orders.
56 //set newOwner = null
57 return this
58 endmethod
59
60 public method onDestroy takes nothing returns nothing
61 //start members
62 set this.m_unit = null
63 //members
64 if (this.m_actor != null) then
65 call RemoveUnit(this.m_actor)
66 set this.m_actor = null
67 endif
68 endmethod
69 endstruct
70
71 /// Waits until no video is running.
72 /// @param interval Check interval.
73 function waitForVideo takes real interval returns nothing
74 loop
75 exitwhen (AVideo.runningVideo == 0)
76 call TriggerSleepAction(interval)
77 endloop
78 endfunction
79
80 /// @todo Should be a part of @struct AVideo, vJass bug.
81 function interface AVideoInitAction takes AVideo video returns nothing
82
83 /// @todo Should be a part of @struct AVideo, vJass bug.
84 function interface AVideoPlayAction takes AVideo video returns nothing
85
86 /// @todo Should be a part of @struct AVideo, vJass bug.
87 function interface AVideoStopAction takes AVideo video returns nothing
88
89 /**
90 * Provides access to a global video. Global means that the video is played/shown for all character owners.
91 * The ASL character system doesn't support local videos which means videos for each single character owner.
92 * Videos can have initialization, play and stop actions which has to be defined as function interface functions.
93 * User can easily save and restore actors data by using methods @method saveActor and @method restoreActor.
94 * Additionally there is a method called @method actor which gives user access to an almost exact copy of the "first character".
95 * The first character is always the character of first player in list which still is online. List is starting with player 1 (id 0).
96 * Since you don't use character units (beside the copied one) they will be hidden in video initialization.
97 * Besides all units will be paused so you have to unpause a unit if you want to give orders (like move) to it.
98 * Videos can be skipped by pressing a user-defined key. If at least half of players want to skip a video (have pressed that key) it will be skipped.
99 */
100 struct AVideo
101 //static start members
102 private static integer divident
103 private static real filterDuration
104 private static real waitInterval
105 private static string textPlayerSkips
106 private static string textSkip
107 //static members
108 private static real waitTime
109 public static thistype runningVideo /// Do not access.
110 private static boolean skipped
111 private static integer skippingPlayers
112 private static trigger skipTrigger
113 private static AActorData m_actor //copy of first character
114 private static APlayerSelection array m_playerSelection[12] /// @todo bj_MAX_PLAYERS
115 private static boolean array m_playerHadDialog[12] /// @todo bj_MAX_PLAYERS
116 private static AIntegerVector m_actorData
117 //start members
118 private AVideoInitAction initAction
119 private AVideoPlayAction playAction
120 private AVideoStopAction stopAction
121
122 //! runtextmacro optional A_STRUCT_DEBUG("\"AVideo\"")
123
124 //methods
125
126 public method play takes nothing returns nothing
127 local force playersAll
128 debug if (thistype.runningVideo != 0) then
129 debug call this.print("Another Video is already running.")
130 debug endif
131
132 call CinematicFadeBJ(bj_CINEFADETYPE_FADEOUT, thistype.waitTime, "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 100.00, 100.00, 100.00, 0.0)
133 call TriggerSleepAction(thistype.waitTime)
134 /// @todo disable experience gain of all characters?
135 call thistype.savePlayerData()
136 call ClearSelection()
137 call ACharacter.setAllMovable(false)
138 call ACharacter.showAll(false)
139 call PauseAllUnits(true)
140 call SetCameraBoundsToRect(bj_mapInitialPlayableArea) // for all players
141 set playersAll = GetPlayersAll()
142 call CinematicModeExBJ(true, playersAll, 0.0)
143 set playersAll = null
144 set thistype.runningVideo = this
145 if (this.initAction != 0) then
146 call this.initAction.execute(this)
147 endif
148 call CinematicFadeBJ(bj_CINEFADETYPE_FADEIN, thistype.waitTime, "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 100.00, 100.00, 100.00, 0.0)
149 call TriggerSleepAction(thistype.waitTime)
150 call EnableTrigger(thistype.skipTrigger)
151 //call EnableUserControl(true) //otherwise we could not catch the press event (just the escape key)
152 call this.playAction.execute(this)
153 endmethod
154
155 /// You have to call this method at the end of your video action.
156 /// Since there is an execution of the action, TriggerSleepAction functions will be ignored, so this method could not be called by the play method.
157 public method stop takes nothing returns nothing
158 local force playersAll
159 debug call Print("Stop!")
160 call DisableTrigger(thistype.skipTrigger)
161 call EnableUserControl(false)
162 call CinematicFadeBJ(bj_CINEFADETYPE_FADEOUT, thistype.waitTime, "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 100.00, 100.00, 100.00, 0.0)
163 call TriggerSleepAction(thistype.waitTime)
164 set playersAll = GetPlayersAll()
165 call CinematicModeExBJ(false, playersAll, 0.0)
166 call EnableUserControl(false)
167 set playersAll = null
168 call ResetToGameCamera(0.0)
169 if (thistype.m_actor != 0) then
170 call thistype.m_actor.restore()
171 call thistype.m_actor.destroy()
172 set thistype.m_actor = 0
173 endif
174 call ACharacter.showAll(true)
175 call PauseAllUnits(false)
176 if (this.stopAction != 0) then
177 call this.stopAction.execute(this)
178 endif
179 call CinematicFadeBJ(bj_CINEFADETYPE_FADEIN, thistype.waitTime, "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 100.00, 100.00, 100.00, 0.0)
180 call TriggerSleepAction(thistype.waitTime)
181 call thistype.restorePlayerData()
182 call EnableUserControl(true)
183
184 call ACharacter.setAllMovable(true)
185 set thistype.runningVideo = 0
186 set thistype.skipped = false
187 set thistype.skippingPlayers = 0
188 //No camera pan! Call it manually, please.
189 endmethod
190
191 /// Waits in video.
192 /// @return Returns true if video was skipped
193 public method wait takes real seconds returns boolean
194 loop
195 set seconds = seconds - thistype.waitInterval
196 if (thistype.skipped) then
197 return true
198 elseif (seconds <= 0) then
199 return false
200 endif
201 call TriggerSleepAction(thistype.waitInterval)
202 endloop
203 return false
204 endmethod
205
206 public static method create takes AVideoInitAction initAction, AVideoPlayAction playAction, AVideoStopAction stopAction returns thistype
207 local thistype this = thistype.allocate()
208 //start members
209 set this.initAction = initAction
210 set this.playAction = playAction
211 set this.stopAction = stopAction
212
213 return this
214 endmethod
215
216 private static method triggerConditionSkip takes nothing returns boolean
217 return thistype.runningVideo != 0
218 endmethod
219
220 private static method triggerActionSkip takes nothing returns nothing
221 local integer i
222 local player triggerPlayer = GetTriggerPlayer()
223 local player user
224 local integer skipablePlayers = 0
225 set thistype.skippingPlayers = thistype.skippingPlayers + 1
226 call ACharacter.displayMessageToAll(ACharacter.messageTypeInfo, StringArg(thistype.textPlayerSkips, GetPlayerName(triggerPlayer))) //AClassCharacterCharacter, ALibraryStringConversion
227 set triggerPlayer = null
228
229 //Jedes Mal neu berechnen, da Spieler as Spiel auch verlassen haben könnten.
230 set i = 0
231 loop
232 exitwhen (i == bj_MAX_PLAYERS)
233 set user = Player(i)
234 if (IsPlayerPlayingUser(user)) then //ALibraryGeneralPlayer
235 set skipablePlayers = skipablePlayers + 1
236 endif
237 set user = null
238 set i = i + 1
239 endloop
240
241 if (thistype.skippingPlayers >= skipablePlayers / 2) then
242 set thistype.skipped = true
243 call DisableTrigger(thistype.skipTrigger) //do not allow skipping at twice!
244 call ACharacter.displayMessageToAll(ACharacter.messageTypeInfo, thistype.textSkip)
245 call thistype.runningVideo.stop()
246 endif
247 endmethod
248
249 private static method createSkipTrigger takes nothing returns nothing
250 local integer i
251 local player user
252 local event triggerEvent
253 local conditionfunc conditionFunction
254 local triggercondition triggerCondition
255 local triggeraction triggerAction
256 set thistype.skipTrigger = CreateTrigger()
257 call DisableTrigger(thistype.skipTrigger) //will be enabled by first running video
258 set i = 0
259 loop
260 exitwhen (i == bj_MAX_PLAYERS)
261 set user = Player(i)
262 if (IsPlayerPlayingUser(user)) then
263 set triggerEvent = TriggerRegisterKeyEventForPlayer(user, thistype.skipTrigger, AKeyEscape, true) //ALibraryInterfaceMisc, important: If it is the escape key it is the same key as in the character selection.
264 set triggerEvent = null
265 endif
266 set user = null
267 set i = i + 1
268 endloop
269 set conditionFunction = Condition(function thistype.triggerConditionSkip)
270 set triggerCondition = TriggerAddCondition(thistype.skipTrigger, conditionFunction)
271 set triggerAction = TriggerAddAction(thistype.skipTrigger, function thistype.triggerActionSkip)
272 set triggerEvent = null
273 set conditionFunction = null
274 set triggerCondition = null
275 set triggerAction = null
276 endmethod
277
278 /// @param divident This value represents the divident which is used for comparing the number of skipping players with the number of requested skipping players for skipping the video.
279 public static method init takes integer divident, real filterDuration, real waitInterval, string textPlayerSkips, string textSkip returns nothing
280 local integer i
281 local player user
282 //static start members
283 set thistype.divident = divident
284 set thistype.filterDuration = filterDuration
285 set thistype.waitInterval = waitInterval
286 set thistype.textPlayerSkips = textPlayerSkips
287 set thistype.textSkip = textSkip
288 //static members
289 set thistype.waitTime = filterDuration / 2
290 set thistype.runningVideo = 0
291 set thistype.skipped = false
292 set thistype.skippingPlayers = 0
293 set thistype.m_actor = 0
294 set thistype.m_actorData = AIntegerVector.create()
295 set i = 0
296 loop
297 exitwhen (i == bj_MAX_PLAYERS)
298 set user = Player(i)
299 if (IsPlayerPlayingUser(user)) then
300 set thistype.m_playerSelection[i] = 0
301 endif
302 set user = null
303 set i = i + 1
304 endloop
305
306 call thistype.createSkipTrigger()
307 endmethod
308
309 private static method destroySkipTrigger takes nothing returns nothing
310 call AHashTable.global().destroyTrigger(thistype.skipTrigger)
311 set thistype.skipTrigger = null
312 endmethod
313
314 public static method cleanUp takes nothing returns nothing
315 //static members
316 loop
317 exitwhen (thistype.m_actorData.empty())
318 call AActorData(thistype.m_actorData.back()).destroy()
319 call thistype.m_actorData.popBack()
320 endloop
321 call thistype.m_actorData.destroy()
322
323 call thistype.destroySkipTrigger()
324 endmethod
325
326 //static members
327
328 public static method wasSkipped takes nothing returns boolean
329 return thistype.skipped
330 endmethod
331
332 //static memthods
333
334 public static method isRunning takes nothing returns boolean
335 return thistype.runningVideo != 0
336 endmethod
337
338 public static method actor takes nothing returns unit
339 debug if (thistype.runningVideo == 0) then
340 debug call thistype.staticPrint("Running video is 0.")
341 debug endif
342 if (thistype.m_actor == 0) then
343 set thistype.m_actor = AActorData.create(ACharacter.getFirstCharacter().unit())
344 endif
345 return thistype.m_actor.actor()
346 endmethod
347
348 public static method saveUnitActor takes unit actor returns integer
349 local AActorData data = AActorData.create(actor)
350 call thistype.m_actorData.pushBack(data)
351 return thistype.m_actorData.backIndex()
352 endmethod
353
354 public static method unitActor takes integer index returns unit
355 return AActorData(thistype.m_actorData[index]).actor()
356 endmethod
357
358 public static method restoreUnitActor takes integer index returns nothing
359 call AActorData(thistype.m_actorData[index]).restore()
360 call AActorData(thistype.m_actorData[index]).destroy()
361 call thistype.m_actorData.erase(index)
362 endmethod
363
364 public static method restoreUnitActorOnActorLocation takes integer index returns nothing
365 call AActorData(thistype.m_actorData[index]).restoreOnActorsLocation()
366 call AActorData(thistype.m_actorData[index]).destroy()
367 call thistype.m_actorData.erase(index)
368 endmethod
369
370 public static method restoreUnitActors takes nothing returns nothing
371 loop
372 exitwhen (thistype.m_actorData.empty())
373 call thistype.restoreUnitActor(thistype.m_actorData.backIndex())
374 endloop
375 endmethod
376
377 public static method restoreUnitActorsOnActorsLocations takes nothing returns nothing
378 loop
379 exitwhen (thistype.m_actorData.empty())
380 call thistype.restoreUnitActorOnActorLocation(thistype.m_actorData.backIndex())
381 endloop
382 endmethod
383
384 public static method setActorsMoveSpeed takes real moveSpeed returns nothing
385 local integer i = 0
386 loop
387 exitwhen (i == thistype.m_actorData.size())
388 call SetUnitMoveSpeed(AActorData(thistype.m_actorData[i]).actor(), moveSpeed)
389 set i = i + 1
390 endloop
391 endmethod
392
393 private static method savePlayerData takes nothing returns nothing
394 local player user
395 local integer i = 0
396 loop
397 exitwhen (i == bj_MAX_PLAYERS)
398 set user = Player(i)
399 if (IsPlayerPlayingUser(user)) then
400 if (thistype.m_playerSelection[i] == 0) then
401 set thistype.m_playerSelection[i] = APlayerSelection.create(user)
402 endif
403 call thistype.m_playerSelection[i].save()
404 if (AGui.playerGui(user).dialog().isDisplayed()) then
405 set thistype.m_playerHadDialog[i] = true
406 call AGui.playerGui(user).dialog().hide()
407 else
408 set thistype.m_playerHadDialog[i] = false
409 endif
410 endif
411 set user = null
412 set i = i + 1
413 endloop
414 endmethod
415
416 private static method restorePlayerData takes nothing returns nothing
417 local player user
418 local integer i = 0
419 loop
420 exitwhen (i == bj_MAX_PLAYERS)
421 set user = Player(i)
422 if (IsPlayerPlayingUser(user)) then
423 if (thistype.m_playerHadDialog[i]) then
424 call AGui.playerGui(user).dialog().show()
425 endif
426 endif
427 if (thistype.m_playerSelection[i] != 0) then
428 call thistype.m_playerSelection[i].restore()
429 endif
430 set user = null
431 set i = i + 1
432 endloop
433 endmethod
434 endstruct
435
436 endlibrary